package design.patterns;

/**
 * 单例模式(懒汉)
 * 双重判断 线程安全 保证并发效率
 *
 * 6阶段再优化 volatile
 */
public class LazySingleton {
    private LazySingleton() {
    }

    /**
     * volatile 主要用于描述类中的属性
     * 1.保证线程的可见性(对变量的修改可以直接同步给其他线程)
     * 2.禁止指令重排序(JVM为保证效率,可能会动态调整指令额执行顺序)
     */
    private static volatile LazySingleton instance = null;

    public static LazySingleton getInstance() {
        //第一层if是为了判断当前是否已经把实例创建出来，存在对象直接返回无需创建
        if (instance == null) {
            //第二层synchronized是为了使进入当前if中的线程来竞争锁
            synchronized (LazySingleton.class) {
                //当拿到锁的线程进入到第三层if之后判断是否为空
                if (instance == null) {
                    //为空时实例化对象，然后再释放锁
                    instance = new LazySingleton();
                    //执行的指令:
                    //1.分配空间
                    //2.属性默认初始化
                    //3.调用构造方法
                    //4.将对象地址值付给instance变量
                    //1-4-(此时其他线程进入第一个if返回对象,会出现NPE)-2-3
                    /*
                    释放锁之后，instance已经不为空了，后面的线程就被阻挡在了第三层if这里了，
                    之后再来访问getInstance()方法，发现该instance已经不为空了，也就不用再抢占锁资源了，
                    因为竞争锁也消耗大量的时间。通过这样处理，既保证了线程安全，也提高了效率。
                     */
                }
            }
        }
        return instance;
    }
}
